<?php
/**
* @name 将数组转换为xml对象
*
* @param array $data 数据数组
* @param $case 转换key为大写或小写  默认小写
* @param string $rootNodeName - what you want the root node to be - defaultsto data.
* @param SimpleXMLElement $xml - should only be used recursively
* @return string XML
*/
function arrtoXml($data , $case = CASE_LOWER , $rootNodeName = 'root', $xml = null)
{
    if(!is_array($data)){
        return $data;
    }
    // turn off compatibility mode as simple xml throws a wobbly if you don't.
    if (ini_get('zend.ze1_compatibility_mode') == 1){
        ini_set ('zend.ze1_compatibility_mode', 0);
    }
    if(empty($data)){
        return "<$rootNodeName><data>null</data></$rootNodeName>";
    }
    if ($xml == null){
        $rootNodeName = $case==CASE_LOWER ? strtolower($rootNodeName):strtoupper($rootNodeName);
        $xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName />");
    }
    
    foreach($data as $key => $value){
        if (is_numeric($key)){
            $key = 'item';
        }
        //replace anything not alpha numeric
        //$key = preg_replace('/[^a-z]/i', '', $key);
        $key = $case==CASE_LOWER ? strtolower($key):strtoupper($key);
        $value = is_object($value) ? (array)$value : $value;
        if (is_array($value)){
            if(empty($value)){
                $xml->addChild($key,'null');
                continue;
            }
            $node = $xml->addChild($key);
            // recrusive call.// 
            arrtoXml($value,$case, $rootNodeName, $node);
        }else {
            $value = htmlentities($value);
            if($value === false){
                $value = 'false';
            }elseif($value === 0 || $value === 1){
                $value = (string)$value;
            }elseif($value === true || $value == 'true'){
                $value = 'true';
            }elseif($value === ''){
                $value = 'null';
            }
            //$value = ($value === false || $value === '0') ? 'false' : ($value == ''  ? 'null' : (($value == '1' || $value == 'true') ? 'true' : $value));
            $xml->addChild($key,$value);
        }
        
    }
    // return xml
    return str_replace(array('<>','</>'),'',$xml->asXML());
}
/**
 * @name 递归将数组键,值转为大写或小写
 * @param array $data 转换的数组
 * @param $type 转换的类型 大写(CASE_UPPER)或者小写 (default:CASE_LOWER)
 * @return array $data
 */
function arr_change_case_value($data,$type = CASE_LOWER )
{
    if(is_array($data)){
        $data = array_change_key_case($data,$type);
        foreach($data as $k=>&$v){
            if(is_array($v)){
                $v = arr_change_case_value($v,$type);
            }
        }
    }
    return $data;
    
}

/**
 * @name 检查字符串是否是UTF8编码
 * @param string $string 字符串
 * @return Boolean
 */
if(!function_exists('is_utf8'))
{
    function is_utf8($string) {
        return preg_match('%^(?:
             [\x09\x0A\x0D\x20-\x7E]            # ASCII
           | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
           |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
           | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
           |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
           |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
           | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
           |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
       )*$%xs', $string);
    }
}
/**
 * @name 检测字符串是不是json数据格式
 * @param string $string 字符串
 * @return boolen
 */
function is_json($string) 
{
    if(!is_string($string)) return $string;
    json_decode($string); 
    return (json_last_error() == JSON_ERROR_NONE);
}
/**
 * @name 获取API错误信息
 * @param string $code_id 错误代码ID
 * @return array 错误信息数组  ['code'=>code,'message'=>message]
 */
function getApiErrorCode($code_id = '')
{
    $codeModel = new \app\common\model\Errorcode();
    $code = $codeModel->getCode();
    return $code_id ? array('code'=>$code_id,'message'=>$code[$code_id]) : $code;
}
/**
 * @name 对象转数组方法
 * @param object $data 对象信息
 * @return array 转换后的数组
 */
function object2array($data) 
{  
    if(is_object($data)) {  
        $data = (array)$data;  
    }
    if(is_array($data)) {  
        foreach($data as $key=>&$value) {  
         $value = object2array($value);  
        }  
    }  
     return $data;  
}
/**
 * @name 标签过滤
 */
function real_strip_tags($str, $allowable_tags="") 
{
    $str = html_entity_decode($str,ENT_QUOTES,'UTF-8');
    return strip_tags($str, $allowable_tags);
}


/** 
 * @name h函数用于过滤不安全的html标签，输出安全的html
 * @param string $text 待过滤的字符串
 * @param string $type 保留的标签格式
 * @return string 处理后内容
 */
function h($text, $type = 'html')
{
    // 无标签格式
    $text_tags  = '';
    //只保留链接
    $link_tags  = '<a>';
    //只保留图片
    $image_tags = '<img>';
    //只存在字体样式
    $font_tags  = '<i><b><u><s><em><strong><font><big><small><sup><sub><bdo><h1><h2><h3><h4><h5><h6>';
    //标题摘要基本格式
    $base_tags  = $font_tags.'<p><br><hr><a><img><map><area><pre><code><q><blockquote><acronym><cite><ins><del><center><strike>';
    //兼容Form格式
    $form_tags  = $base_tags.'<form><input><textarea><button><select><optgroup><option><label><fieldset><legend>';
    //内容等允许HTML的格式
    $html_tags  = $base_tags.'<meta><ul><ol><li><dl><dd><dt><table><caption><td><th><tr><thead><tbody><tfoot><col><colgroup><div><span><object><embed><param>';
    //专题等全HTML格式
    $all_tags   = $form_tags.$html_tags.'<!DOCTYPE><html><head><title><body><base><basefont><script><noscript><applet><object><param><style><frame><frameset><noframes><iframe>';
    //过滤标签
    $text = real_strip_tags($text, ${$type.'_tags'});
    // 过滤攻击代码
    if($type != 'all') {
        // 过滤危险的属性，如：过滤on事件lang js
        while(preg_match('/(<[^><]+)(ondblclick|onclick|onload|onerror|unload|ontouch|onmousemove|onmouseover|onmouseup|onmouseout|onmousedown|onkeydown|onkeypress|onkeyup|onblur|onchange|onfocus|action|background|codebase|dynsrc|lowsrc)([^><]*)/i',$text,$mat)){
            $text = str_ireplace($mat[0], $mat[1].$mat[3], $text);
        }
        while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){
            $text = str_ireplace($mat[0], $mat[1].$mat[3], $text);
        }
    }
    return $text;
}
/**
 * @name string_filter函数用于过滤标签，输出没有html的干净的文本
 * @access public
 * @param string text 文本内容
 * @return string 处理后内容
 */
function string_filter($text)
{
    $text = nl2br($text);
    $text = real_strip_tags($text);
    $text = addslashes($text);
    $text = trim($text);
    return $text;
}
/**
 * @name 获取客户端IP地址
 * @access public
 * @return string 返回获取的IP信息
 */
function get_client_ip($type = 0) 
{
    $type       =  $type ? 1 : 0;
    static $ip  =   NULL;
    if ($ip !== NULL) return $ip[$type];
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $pos    =   array_search('unknown',$arr);
        if(false !== $pos) unset($arr[$pos]);
        $ip     =   trim($arr[0]);
    }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
        $ip     =   $_SERVER['HTTP_CLIENT_IP'];
    }elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip     =   $_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法验证
    $long = sprintf("%u",ip2long($ip));
    $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
}
/**
 * @name 取一个二维数组中的每个数组的固定的键知道的值来形成一个新的一维数组
 * @access public
 * @param $pArray 一个二维数组
 * @param $pKey 数组的键的名称
 * @return 返回新的一维数组
 */
function getSubByKey($pArray, $pKey="", $pCondition="")
{
    $result = array();
    if(is_array($pArray)){
        foreach($pArray as $temp_array){
            if(is_object($temp_array)){
                $temp_array = (array) $temp_array;
            }
            if((""!=$pCondition && $temp_array[$pCondition[0]]==$pCondition[1]) || ""==$pCondition) {
                $result[] = (""==$pKey) ? $temp_array : isset($temp_array[$pKey]) ? $temp_array[$pKey] : "";
            }
        }
        return $result;
    }else{
        return false;
    }
}
/**
 * @name 获取字符串大写的首字母
 * @access public
 * @param string $so 字符串
 * @return string 首字母
 */
function getFirstLetter($s0) 
{
    $firstchar_ord = ord(strtoupper($s0{0}));
    if($firstchar_ord >= 65 and $firstchar_ord <= 91) return strtoupper($s0{0});
    if($firstchar_ord >= 48 and $firstchar_ord <= 57) return '#';
    $s = iconv("UTF-8", "gb2312", $s0);
    $asc = ord($s{0}) * 256 + ord($s{1}) - 65536;
    if($asc>=-20319 and $asc<=-20284) return "A";
    if($asc>=-20283 and $asc<=-19776) return "B";
    if($asc>=-19775 and $asc<=-19219) return "C";
    if($asc>=-19218 and $asc<=-18711) return "D";
    if($asc>=-18710 and $asc<=-18527) return "E";
    if($asc>=-18526 and $asc<=-18240) return "F";
    if($asc>=-18239 and $asc<=-17923) return "G";
    if($asc>=-17922 and $asc<=-17418) return "H";
    if($asc>=-17417 and $asc<=-16475) return "J";
    if($asc>=-16474 and $asc<=-16213) return "K";
    if($asc>=-16212 and $asc<=-15641) return "L";
    if($asc>=-15640 and $asc<=-15166) return "M";
    if($asc>=-15165 and $asc<=-14923) return "N";
    if($asc>=-14922 and $asc<=-14915) return "O";
    if($asc>=-14914 and $asc<=-14631) return "P";
    if($asc>=-14630 and $asc<=-14150) return "Q";
    if($asc>=-14149 and $asc<=-14091) return "R";
    if($asc>=-14090 and $asc<=-13319) return "S";
    if($asc>=-13318 and $asc<=-12839) return "T";
    if($asc>=-12838 and $asc<=-12557) return "W";
    if($asc>=-12556 and $asc<=-11848) return "X";
    if($asc>=-11847 and $asc<=-11056) return "Y";
    if($asc>=-11055 and $asc<=-10247) return "Z";
    return '#';
}

/**
 * @name @name 格式化Emoji
 * @param boolean $type true为将emoji格式化为代码，false为将代码格式化为emoji
 * @param string|array 数据，如果数数组，就递归，解析多维内部数据
 * @return string 格式化的数据
 **/
function formatEmoji($data,$type = false )
{
    if (is_array($data)) {
        foreach ($data as $key => $value) {
            $data[$key] = formatEmoji($type, $data);
        }
        return $data;
    } elseif ($type) {
        return preg_replace_callback('/[\xf0-\xf7].{3}/', function ($data) {
            $data = array_pop($data);
            $data = base64_encode($data);
            $data = '[emoji:' . $data . ']';
            return $data;
        }, $data);
    }
    return preg_replace_callback('/\[emoji\:(.*?)\]/is', function ($data) {
            $data = $data[1];
            $data = base64_decode($data);
            return $data;
        }, $data);
}
/**
 * @name 计算时间差函数
 * @access public
 * @param int $begin_time 开始时间戳default:NOW_TIME;
 * @param int $end_time 结束时间戳
 * @return string 时间差描述
 */
function getTimediff($begin_time,$end_time){
    $begin_time = (float)$begin_time ? (float)$begin_time : time();//开始时间 时间戳
    $end_time = (float)$end_time ? (float)$end_time : time();//结束时间 时间戳
    $cle = $end_time - $begin_time; //得出时间戳差值
    $str = '';
    if($cle <= 0) return $str;
    $day = floor($cle/3600/24);
    
    $hours = floor(($cle%(3600*24))/3600);
    $minutes = floor(($cle%(3600*24))%3600/60);
    $second = floor(($cle%(3600*24))%60);
    $day > 0 &&
    $str .= $day . '天';
    
    if($hours > 0 || ($minutes > 0 || $second > 0 || $minutes > 0) && $day > 0) {
        $str.= $hours . '小时';
    }
    
    if($minutes > 0 || ($minutes > 0 || $second > 0) && ($day > 0 || $hours > 0)) {
        $str .= $minutes . '分钟';
    }
    
    $second > 0 &&
    $str .= $second . '秒';
    
    return $str;
}
/**
 * @name 获取保存图片的名称
 * @param $filename 图片原名称
 * @param $uid 用户uid(非加密)
 */
function getFileName($filename = '',$uid = 0){
    return md5($filename.time().'_'.$uid);
}

/**
 * @name 字节格式化 把字节数格式为 B K M G T 描述的大小
 * @param int $size 字节
 * @param int 保留位数
 * @return string 转换的后的描述字符串
 */
function byte_format($size, $dec=2) {
    $a = array("B", "KB", "MB", "GB", "TB", "PB");
    $pos = 0;
    while ($size >= 1024) {
         $size /= 1024;
           $pos++;
    }
    return round($size,$dec)." ".$a[$pos];
}

/**
 * @name 采用进制数处理例如id,uid之类的数据
 * @access public
 * @return string 加密后的字符串
 */
function encrypt_id($txt = ''){
    //取当前时间戳
    $key = time();
    return 'i'.jiami(base_convert($key,10,36).'.'.$txt);
}
/**
 * @name 解密对id,uid之类的数据
 * @access public
 * @return string 加密后的id
 */
function decrypt_id($text = ''){
    if(substr($text,0,1) != 'i'){
        return 0;
    }
    $text = substr($text,1);
    $res = explode('.',jiemi($text),2);
    $key = base_convert($res[0],36,10);
    if(!(int)$key){
        return 0;
    }
    return $res[1];
}

/**
 * @name 定义常量,判断是否未定义.
 * @param string $name 常量名
 * @param string $value 常量值
 * @return string $str 返回常量的值
 */
function zbdefine($name,$value) {
	//定义未定义的常量
	if(!defined($name)){
		//定义新常量
		define($name,$value);
	}else{
		//返回已定义的值
		$value = constant($name);
	}
	return $value;
}
/**
 * @name 实例化模型,支持直接调用方法
 * @param string $name 类名
 * @param array $function 参数数组  [0 => 方法名 1=>参数],多个参数以数组传递
 * @return object|result 返回类或者执行方法的结果
 */
function model($name = '',$function = []){
    if($function){
        $function_name = $function[0];
        $function_param = (array)$function[1];
        return call_user_func_array([D($name),$function_name],$function_param);
    }
    return D($name);
}
/**
 * @name 快速清理缓存的方法
 */
function cleanData($uid = 0 , $type = '' , $format = false){
    switch($type){
        case 'stream':
            S('stream_array_' . $uid, null);
		    S('stream_object_' . $uid, null);
            break;
        case 'cover':
        case 'avatar':
            $suffix = $format ? 'true' : 'false';
            S('info_user_'.$uid.'_'.$suffix,null);
            break;
        default:
            return false;
    }
    return true;
}

/**
 * 对多维数组进行排序
 * @param $multi_array 数组
 * @param $sort_key需要传入的键名
 * @param $sort排序类型
 */
function multi_array_sort($multi_array, $sort_key, $sort = SORT_DESC) {
    if (is_array($multi_array)) {
        foreach ($multi_array as $row_array) {
            if (is_array($row_array)) {
                $key_array[] = $row_array[$sort_key];
            } else {
                return false;
            }
        }
    } else {
        return false;
    }
    array_multisort($key_array, $sort, $multi_array);
    return $multi_array;
}

/**
 * @name 取得IM服务器的用户UID
 */
function getImUID($uid = 0){
    return (int)$uid+600000;
}
/**
 * @name 取得本地用户UID
 */
function getLocalUID($uid = 0){
    $uid = (int)$uid-600000;
    return $uid <= 0 ? 0 :$uid;
}
/**
 * @name 根据UID获取用户昵称
 */
function getUname($uid = 0){
    if($uid){
        return getUser($uid,'uname')['uname'];
    }
    return '';
}
/**
 * @name 根据UID获取指定的信息
 * @param int $uid 用户UID
 * @param array $info 需要获取的用户信息数组
 * @return array 用户信息
 */
function getUser($uid = 0,$info = []){
    if(!is_array($info)){
        $info = array_filter(explode(',',$info));
    }
    $user = model('open/User')->getUserInfo($uid);
    $user['uid'] = encrypt_id($user['uid']);
    $result = [];
    if($info){
        foreach($info as $v){
            if(is_object($user[$v])){
                $user[$v] = (array)$user[$v];
            }
            $result = array_merge($result,[$v=>$user[$v]]);
        }
    }else{
       $result = $user; 
    }
    return $result;
}
//加密函数
function jiami($txt, $key = null) {
    if (empty ( $key ))
        $key = C ( 'SECURE_CODE' );
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=_";
    $nh = rand ( 0, 64 );
    $ch = $chars [$nh];
    $mdKey = md5 ( $key . $ch );
    $mdKey = substr ( $mdKey, $nh % 8, $nh % 8 + 7 );
    $txt = base64_encode ( $txt );
    $tmp = '';
    $i = 0;
    $j = 0;
    $k = 0;
    for($i = 0; $i < strlen ( $txt ); $i ++) {
        $k = $k == strlen ( $mdKey ) ? 0 : $k;
        $j = ($nh + strpos ( $chars, $txt [$i] ) + ord ( $mdKey [$k ++] )) % 64;
        $tmp .= $chars [$j];
    }
    return $ch . $tmp;
}

//解密函数
function jiemi($txt, $key = null) {
    if (empty ( $key ))
        $key = C ( 'SECURE_CODE' );
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=_";
    $ch = $txt [0];
    $nh = strpos ( $chars, $ch );
    $mdKey = md5 ( $key . $ch );
    $mdKey = substr ( $mdKey, $nh % 8, $nh % 8 + 7 );
    $txt = substr ( $txt, 1 );
    $tmp = '';
    $i = 0;
    $j = 0;
    $k = 0;
    for($i = 0; $i < strlen ( $txt ); $i ++) {
        $k = $k == strlen ( $mdKey ) ? 0 : $k;
        $j = strpos ( $chars, $txt [$i] ) - $nh - ord ( $mdKey [$k ++] );
        while ( $j < 0 )
            $j += 64;
        $tmp .= $chars [$j];
    }
    return base64_decode ( $tmp );
}
/**
 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
 * @param $para 需要拼接的数组
 * @return 拼接完成以后的字符串
 */
function createLink($para) {
	$arg  = "";
	while (list ($key, $val) = each ($para)) {
		$arg.=$key."=".$val."&";
	}
	//去掉最后一个&字符
	$arg = substr($arg,0,count($arg)-2);
	
	//如果存在转义字符，那么去掉转义
	if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
	
	return $arg;
}
/**
  * @name 返回数组的维度
  * @param array $arr 数组
  * @return int 数组维度
  */
function arrayLevel($arr){
    $al = array(0); 
    aL($arr,$al); 
    return max($al); 
}
function aL($arr,&$al,$level=0){ 
    if(is_array($arr)){ 
        $level++; 
        $al[] = $level; 
        foreach($arr as $v){ 
            aL($v,$al,$level); 
        } 
    } 
} 
/**
 * @name 读取 去重\缓存.
 * @param string $filename 载入的文件名
 * @return boolean
 */
function zb_read_file($filename,$path = '') {
	
	static $_readFiles = array();	//已载入的文件列表缓存
	
	$key = strtolower($filename);
	if (false !== $_readFiles[$key]) {
		!$path && $path = APP_PATH . MODULE_NAME .'/';
		if (is_file($filename)) {
			$content = require_once $filename;
			$_readFiles[$key] = $content;
		} elseif(file_exists($path.$filename.EXT)) {
			$content = require_once $path.$filename.EXT;
			$_readFiles[$key] = $content;
		} else {
			$_readFiles[$key] = false;
		}
	}
	return $_readFiles[$key];
}
/**
 * @name 获取图片地址
 * @param int $attach_id 附件ID
 * @param int $size 需要获取的附件大小[-1:所有,0:原图,1,2,3,4,5]
 * @return string|array 如果$size 有效,将返回string ,其他均为array
 */
function getImageUrl($attach_id = 0 ,$size = -1){
    $urls = model('attach/Attach')->getAttachUrl($attach_id);
    if($urls){
        return array_key_exists($size,$urls) ? $urls[$size] : $urls;
    }
}
/**
 * 注册rule规则
 * @param class_name string  类的名称
 * @return str 返回错误或者正确信息
 */
function register($class_name){
    $data=get_class_methods($class_name);
    //把一些父类的方法过滤掉    $arr=array('_initialize','__set','__construct','display','show','fetch','buildHtml','theme','assign',' __set','get','__get','__isset','__call','error','success','ajaxReturn','redirect','__destruct');
    foreach($arr as $k=>$v){
        if(in_array($arr[$k],$data)){
            $tmp=array_keys($data,$arr[$k]);
            unset($data[$tmp[0]]);
        }
    }
    $obj=M("auth_rule");
    $msg='';
    foreach($data as $k=>$v){
        $data[$k]=CONTROLLER_NAME.'/'.$data[$k];
        if(!$obj->where(array('name'=>$data[$k]))->find()){
            if($obj->add(array('name'=>$data[$k]))){
                $msg=$msg.$data[$k].'注册成功\n';
            }else{
                $msg=$msg.$data[$k].'注册失败\n';
            }
        }else{
            $msg=$msg.$data[$k].'已注册\n' ;
        }
    }
    echo "<script>alert('".$msg."');history.back(-1);</script>";
}
/**
 * 控制模板中菜单的显示
 * @param rule string|array  需要验证的规则列表,支持逗号分隔的权限规则或索引数组
 * @param uid  int           认证用户的id
 * @param string mode        执行check的模式
 * @param relation string    如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证
 * @return boolean           通过验证返回true;失败返回false
 */
/*function authCheck($rule,$uid,$type=1, $mode='url', $relation='or'){
    $auth=new \Think\Auth();
    //获取当前uid所在的角色组id
    //$groups=$auth->getGroups($uid);
    if($_SESSION['username']==C('USER_AUTH_KEY')){
      return true;
    }
    return $auth->check($rule,$uid,$type,$mode,$relation)?true:false;
}*/

function authcheck($name, $uid, $type=1, $mode='url', $relation='or'){
    if(!in_array($uid,C('ADMINISTRATOR'))){
        $auth=new \Think\Auth();
        return $auth->check($name, $uid, $type, $mode, $relation)?true:false;
    }else{
        return true;
    }
}
/**
 * @name 数组降维 返回一维数组的值
 * @param array $multi 原数组,可以是多维
 * @return array 返回一维数组
 */
function arr2one($multi){
    $arr = array();
    foreach ($multi as $key => $val) {
        if( is_array($val) ) {
            $arr = array_merge($arr, arr2one($val));
        } else {
            $arr[$key] = $val;
        }
    }
    return $arr;
}
/**
 * @name 字符串截取，支持中文和其它编码
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 * @return string 截取的字符串
 */
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
    if(function_exists("mb_substr")){
        $slice = mb_substr($str, $start, $length, $charset);
    }elseif(function_exists('iconv_substr')) {
        $slice = iconv_substr($str,$start,$length,$charset);
    }else{
        $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("",array_slice($match[0], $start, $length));
    }
    if($suffix && $str != $slice) return $slice."...";
    return $slice;
}
/**
 * @name 获取直播间信息
 */
function getSnapshot($uid = 0){
    return A('stream/Stream')->getSnapshot(false,$uid);
}
function format_num($num = 0){
    if($num > 9999){
        $num = round($num/10000,1);
        $num = strrchr($num,'.') ? $num.'w' : $num.'.0w';
    }elseif($num > 999){
        $num = round($num/1000,1);
        $num = strrchr($num,'.') ? $num.'k' : $num.'.0k';
    }
    return $num;
}
/**
 * @name 记录系统日志
 * @param *string $content 日志信息描述
 * @param *string $type 日志所属模块分类,需要预先在日志model下定义
 * @parma array $ext 日志的扩展信息
 *  ext:可以包含以下字段
 *      key: 日志标记key值,如cleancache
 */
function system_log(string $content,string $type,array $ext){
    $logModel = new \app\admin\model\Log($content,$type,$ext);
    return $logModel->addLog();
}
/**
 * 获取字符串的长度
 *
 * 计算时, 汉字或全角字符占1个长度, 英文字符占0.5个长度
 *
 * @param string  $str
 * @param boolean $filter 是否过滤html标签
 * @return int 字符串的长度
 */
function get_str_length($str, $filter = false){
    if ($filter) {
        $str = html_entity_decode($str, ENT_QUOTES, 'UTF-8');
        $str = strip_tags($str);
    }
    return (strlen($str) + mb_strlen($str, 'UTF8')) / 4;
}


/**
 * 判断是否是在微信浏览器里，根据UA
 * @author Max.Yu <max@jipu.com>
 */
function is_weixin(){
  $agent = $_SERVER['HTTP_USER_AGENT'];
  if(!strpos($agent, 'MicroMessenger')){
    return false;
  }
  return true;
}

/**
 * 判断手机型号 IOS/Android
 * @author buddha <[email address]>
 * @return boolean [description]
 */
function is_android(){
  if(strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone')||strpos($_SERVER['HTTP_USER_AGENT'], 'iPad')){
    return false;
  }else if(strpos($_SERVER['HTTP_USER_AGENT'], 'Android')){
    return true;
  }else{
    return false;
  }
}